﻿using System;
using System.Collections.Generic;
using TuxedoLib;

namespace SpaceSquirrel
{
	public class MapParser
	{
		private Dictionary<string, string> values;

		public MapParser(string file)
		{
			string path = ("maps/" + file).Replace('\\', '/');
			AssetLoader loader = AssetLoader.LoadFromProject(path, typeof(MapParser).Assembly, false);
			loader.LoadData();
			string t = loader.ConvertDataToText();
			Dictionary<string, string> values = new Dictionary<string, string>();
			foreach (string line in t.Split('\n'))
			{
				string[] parts = line.Split(':');
				if (parts.Length < 2)
				{
					continue;
				}

				string key = parts[0].Substring(1).Trim();
				string value = string.Join(":", Util.ArraySlice<string>(parts, 1, 0)).Trim();
				values[key] = value.Trim();
			}
			this.values = values;
		}

		public Map Parse()
		{
			Map m = new Map();
			m.Width = int.Parse(this.values["width"]);
			m.Height = int.Parse(this.values["height"]);
			m.Side = this.GetValue("view", "side").ToLowerInvariant() == "side";
			m.Upper = this.GetTiles(this.values["upper"], m.Width, m.Height);
			m.Lower = this.GetTiles(this.values["lower"], m.Width, m.Height);
			m.Doors = this.GetDoors(this.GetValue("doors", ""));
			m.Enemies = this.GetEnemies(this.GetValue("enemies", ""));
			m.DoorSwaps = this.GetDoorSwaps(this.GetValue("doorswaps", ""));
			m.OverlayTriggers = this.GetOverlayTriggers(this.GetValue("overlay", ""));
			m.Powerups = this.GetPowerUps(this.GetValue("powerups", ""));
			return m;
		}

		// door swap output format:
		// { original ID => List[ Pair<trigger, swapped ID> ] }
		private Dictionary<string, List<Pair<string, string>>> GetDoorSwaps(string strValue)
		{
			strValue = strValue.Trim();
			if (strValue.Length == 0)
			{
				return new Dictionary<string, List<Pair<string, string>>>();
			}

			Dictionary<string, List<Pair<string, string>>> swaps = new Dictionary<string,List<Pair<string, string>>>();
			foreach (string swap in strValue.Split(','))
			{
				string[] parts = swap.Split('|');
				string trigger = parts[0].Trim();
				string original = parts[1].Trim();
				string swapped = parts[2].Trim();


				List<Pair<string, string>> swapList;
				if (!swaps.TryGetValue(original, out swapList))
				{
					swapList = new List<Pair<string, string>>();
					swaps[original] = swapList;
				}

				swapList.Add(new Pair<string, string>(trigger, swapped));
			}
			return swaps;
		}

		private EnemySeed[] GetEnemies(string sv)
		{
			sv = sv.Trim();
			if (sv.Length == 0)
			{
				return new EnemySeed[0];
			}
			List<EnemySeed> enemies = new List<EnemySeed>();
			foreach (string value in sv.Split(','))
			{
				string[] parts = value.Split('|');
				enemies.Add(new EnemySeed()
				{
					ID = parts[0],
					Col = int.Parse(parts[1]),
					Row = int.Parse(parts[2])
				});
			}
			return enemies.ToArray();
		}

		private Door[] GetDoors(string sv)
		{
			sv = sv.Trim();
			if (sv.Length == 0)
			{
				return new Door[0];
			}

			List<Door>doors = new List<Door>();
			foreach (string door in sv.Split(','))
			{
				string[] parts = door.Split('|');
				doors.Add(new Door()
				{
					Target = parts[0],
					SX = int.Parse(parts[1]),
					SY = int.Parse(parts[2]),
					TX = int.Parse(parts[3]),
					TY = int.Parse(parts[4])
				});
			}
			return doors.ToArray();
		}

		private PowerUp[] GetPowerUps(string sv)
		{
			sv = sv.Trim();
			if (sv.Length == 0)
			{
				return new PowerUp[0];
			}

			List<PowerUp> output = new List<PowerUp>();
			foreach (string item in sv.Split(','))
			{
				string[] parts = item.Split('|');
				PowerUp pu = new PowerUp()
				{
					Type = parts[0],
					ID = parts[1],
					Col = int.Parse(parts[2]),
					Row = int.Parse(parts[3])
				};
				output.Add(pu);
			}
			return output.ToArray();
		}

		private TileTemplate[][] GetTiles(string ids, int width, int height)
		{
			List<TileTemplate> output = new List<TileTemplate>();
			foreach (string rawId in ids.Split(','))
			{
				string id = rawId.Trim();
				if (id.Length == 0)
				{
					output.Add(null);
				}
				else
				{
					output.Add(TileStore.GetTile(id));
				}
			}

			TileTemplate[][] grid = SquirrelUtil.MakeGrid<TileTemplate>(width, height);
			int index = 0;
			for (int y = 0; y < height; ++y)
			{
				for (int x = 0; x < width; ++x)
				{
					grid[x][y] = output[index++];
				}
			}
			return grid;
		}

		private Dictionary<string, string> GetOverlayTriggers(string sv)
		{
			sv = sv.Trim();
			if (sv.Length == 0)
			{
				return new Dictionary<string, string>();
			}

			Dictionary<string, string> output = new Dictionary<string, string>();
			foreach (string item in sv.Split(','))
			{
				string[] parts = item.Split('|');
				if (parts.Length == 2)
				{
					output[parts[0].Trim()] = parts[1].Trim();
				}
			}
			return output;
		}

		private string GetValue(string key, string defaultValue)
		{
			if (this.values.ContainsKey(key))
			{
				return this.values[key];
			}
			return defaultValue;
		}
	}

	public class Map
	{
		public int Width { get; set; }
		public int Height { get; set; }
		public bool Side { get; set; }
		public TileTemplate[][] Upper { get; set; }
		public TileTemplate[][] Lower { get; set; }
		public Door[] Doors { get; set; }
		public EnemySeed[] Enemies { get; set; }
		public Dictionary<string, List<Pair<string, string>>> DoorSwaps { get; set; }
		public Dictionary<string, string> OverlayTriggers { get; set; }
		public PowerUp[] Powerups { get; set; }
	}
}
